/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.editor.ext; import java.util.Map; import java.util.HashMap; import javax.swing.event.DocumentListener; import javax.swing.event.DocumentEvent; import javax.swing.text.BadLocationException; import org.netbeans.editor.BaseDocument; import org.netbeans.editor.SyntaxSupport; import org.netbeans.editor.Utilities; import org.netbeans.editor.TokenProcessor; /** * Support methods for syntax analyzes * * @author Miloslav Metelka * @version 1.00 */ public class ExtSyntaxSupport extends SyntaxSupport { /** Listens for the changes on the document. Children can override * the documentModified() method to perform some processing. */ private DocumentListener docL; /** Map holding the [position, local-variable-map] pairs * @associates Map*/ private HashMap localVarMaps = new HashMap(); /** Map holding the [position, global-variable-map] pairs * @associates Map*/ private HashMap globalVarMaps = new HashMap(); public ExtSyntaxSupport(BaseDocument doc) { super(doc); // Create listener to listen on document changes docL = new DocumentListener() { public void insertUpdate(DocumentEvent evt) { documentModified(evt); } public void removeUpdate(DocumentEvent evt) { documentModified(evt); } public void changedUpdate(DocumentEvent evt) { } }; doc.addDocumentListener(docL); } /** Called when the document was modified by either the insert or removal. * @param evt event received with the modification notification. getType() * can be used to obtain the type of the event. */ protected void documentModified(DocumentEvent evt) { // Invalidate variable maps localVarMaps.clear(); globalVarMaps.clear(); } /** Find the type of the variable. The default behavior is to first * search for the local variable declaration and then possibly for * the global declaration and if the declaration position is found * to get the first word on that position. * @return it returns Object to enable the custom implementations * to return the appropriate instances. */ public Object findType(String varName, int varPos) { Object type = null; Map varMap = getLocalVariableMap(varPos); // first try local vars if (varMap != null) { type = varMap.get(varName); } if (type == null) { varMap = getGlobalVariableMap(varPos); // try global vars if (varMap != null) { type = varMap.get(varName); } } return type; } public Map getLocalVariableMap(int pos) { Integer posI = new Integer(pos); Map varMap = (Map)localVarMaps.get(posI); if (varMap == null) { varMap = buildLocalVariableMap(pos); localVarMaps.put(posI, varMap); } return varMap; } protected Map buildLocalVariableMap(int pos) { int methodStartPos = getMethodStartPosition(pos); if (methodStartPos >= 0 && methodStartPos < pos) { VariableMapTokenProcessor vmtp = createVariableMapTokenProcessor(methodStartPos, pos); try { tokenizeText(vmtp, methodStartPos, pos, true); return vmtp.getVariableMap(); } catch (BadLocationException e) { // will default null } } return null; } public Map getGlobalVariableMap(int pos) { Integer posI = new Integer(pos); Map varMap = (Map)globalVarMaps.get(posI); if (varMap == null) { varMap = buildGlobalVariableMap(pos); globalVarMaps.put(posI, varMap); } return varMap; } protected Map buildGlobalVariableMap(int pos) { int docLen = doc.getLength(); VariableMapTokenProcessor vmtp = createVariableMapTokenProcessor(0, docLen); if (vmtp != null) { try { tokenizeText(vmtp, 0, docLen, true); return vmtp.getVariableMap(); } catch (BadLocationException e) { // will default null } } return null; } /** Get the start position of the method or the area * where the declaration can start. */ protected int getMethodStartPosition(int pos) { return 0; // return begining of the document by default } /** Find either the local or global declaration position. First * try the local declaration and if it doesn't succeed, then * try the global declaration. */ public int findDeclarationPosition(String varName, int varPos) { int pos = findLocalDeclarationPosition(varName, varPos); if (pos < 0) { pos = findGlobalDeclarationPosition(varName, varPos); } return pos; } public int findLocalDeclarationPosition(String varName, int varPos) { int methodStartPos = getMethodStartPosition(varPos); if (methodStartPos >= 0 && methodStartPos < varPos) { return findDeclarationPositionImpl(varName, methodStartPos, varPos); } return -1; } /** Get the position of the global declaration of a given variable. * By default it's implemented to use the same token processor as for the local * variables but the whole file is searched. */ public int findGlobalDeclarationPosition(String varName, int varPos) { return findDeclarationPositionImpl(varName, 0, doc.getLength()); } private int findDeclarationPositionImpl(String varName, int startPos, int endPos) { DeclarationTokenProcessor dtp = createDeclarationTokenProcessor(varName, startPos, endPos); if (dtp != null) { try { tokenizeText(dtp, startPos, endPos, true); return dtp.getDeclarationPosition(); } catch (BadLocationException e) { // will default to -1 } } return -1; } protected DeclarationTokenProcessor createDeclarationTokenProcessor( String varName, int startPos, int endPos) { return null; } protected VariableMapTokenProcessor createVariableMapTokenProcessor( int startPos, int endPos) { return null; } /** Token processor extended to get declaration position * of the given variable. */ public interface DeclarationTokenProcessor extends TokenProcessor { /** Get the declaration position. */ public int getDeclarationPosition(); } public interface VariableMapTokenProcessor extends TokenProcessor { /** Get the map that contains the pairs [variable-name, variable-type]. */ public Map getVariableMap(); } } /* * Log * 3 Gandalf 1.2 1/10/00 Miloslav Metelka * 2 Gandalf 1.1 11/14/99 Miloslav Metelka * 1 Gandalf 1.0 11/8/99 Miloslav Metelka * $ */